package site.brood.auth.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import site.brood.auth.pojo.LoginBody;
import site.brood.auth.pojo.RegisterBody;
import site.brood.auth.service.LoginService;
import site.brood.common.core.str.StrUtil;
import site.brood.common.core.user.LoginUserVO;
import site.brood.common.core.web.AjaxJson;
import site.brood.common.security.service.TokenService;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 登陆控制器
 *
 * 外部网络请求流程：
 * 外部网络请求header中带jwt格式token
 * 一、经过网关服务
 * 在网关拦截器中，从jwt中取出userId,userName,userKey，转存到header中，转发给业务微服务
 * 二、内部微服务
 * 1)在请求头拦截器中，取出header中的userId,userName,userKey，转存到TransmittableThreadLocal对象中
 * 通过userKey从redis中取出用户详情，以userKey为key存入TransmittableThreadLocal对象中
 * 2)调用内部feign服务(例如：日志服务)
 * 在feign拦截器中，从主线程request中或TransmittableThreadLocal对象中取出userId,userName,userKey，转存到feign header中
 * 三、日志服务
 * 1)在鉴权注解(RequiresPermissions)的AOP回调中，从TransmittableThreadLocal对象中取出userId,userName,userKey
 * 通过userKey从TransmittableThreadLocal对象中取出用户详情
 * 通过用户详情中的权限列表，与鉴权注解中要求的权限数组比对
 * 鉴权失败抛出鉴权失败异常
 * 四、全局异常AOP
 * 将鉴权失败异常转为AjaxJson对象写入网络response
 */
@RestController
public class LoginController
{
    @Autowired
    private LoginService loginService;

    @Autowired
    private TokenService tokenService;

    @PostMapping("login")
    public AjaxJson postLogin(@RequestBody LoginBody form)
    {
        // 生成jwt格式token及过期时间
        // 将用户详情写入redis
        Map<String, Object> tokenMap = loginService.login(form.getUsername(), form.getPassword());
        // 获取登录token
        return AjaxJson.success(tokenMap);
    }

    @DeleteMapping("/logout")
    public AjaxJson logout(HttpServletRequest request)
    {
        // 记录用户退出日志
        loginService.logout(request);

        return AjaxJson.success();
    }

    @PostMapping("refresh")
    public AjaxJson refresh(HttpServletRequest request)
    {
        LoginUserVO loginUser = tokenService.getLoginUser(request);
        if (StrUtil.isNotNull(loginUser))
        {
            // 刷新令牌有效期
            tokenService.refreshToken(loginUser);
        }
        return AjaxJson.success();
    }

    @PostMapping("register")
    public AjaxJson register(@RequestBody RegisterBody registerBody)
    {
        // 用户注册
        loginService.register(registerBody.getUsername(), registerBody.getPassword());
        return AjaxJson.success();
    }
}
